Linux - return codes
Overview of the most popular return codes in Unix-like systems. The exit and return commands and what their arguments mean.
release date: 2025-09-05
modification date: 2025-09-10
introduction
Most Linux users have surely come across the concept of return code - for example, while reading forums, working in the terminal, executing everyday commands, or encountering errors. This issue may be especially familiar to Termux users, who see a message about this code every time they exit the terminal with a code other than 0 - as shown in the picture below. Other places where it appears include logs of many packages or systemd logs.
Return codes inform the user as well as other processes, programs, or scripts whether a task was successful or not, and why. Different codes indicate different events and reasons for errors. The most common ones are 0 and 1 - no error or an error occurred. But that’s just a taste and a pinch of everything this topic has to offer.

types of return codes
Every program, script, or process can theoretically return any value as its return code. In practice, however, the return code value is an 8-bit value (0..255) - which means there are 0-255 actual return codes, of which only a smaller portion have any practical use and convey meaningful information.
Below is a table containing the most common return codes (in Bash) along with a brief note. We will look at the details of some of them later in the article.
Below is a table containing the most common return codes (in Bash) along with a brief note. We will look at the details of some of them later in the article.
Code | Description |
---|---|
0 | Success |
1 | Operation not permitted / General return |
2 | No such file or directory |
3 | No such process |
4 | Interrupted system call |
5 | Input/output error |
6 | No such device or address |
7 | Argument list too long |
8 | Exec format error |
9 | Bad file descriptor |
10 | No child processes |
11 | Resource temporarily unavailable |
12 | Cannot allocate memory |
13 | Permission denied |
14 | Bad address |
15 | Block device required |
16 | Device or resource busy |
17 | File exists |
18 | Invalid cross-device link |
19 | No such device |
20 | Not a directory |
21 | Is a directory |
22 | Invalid argument |
23 | Too many open files in system |
24 | Too many open files |
25 | Inappropriate ioctl for device |
26 | Text file busy |
27 | File too large |
28 | No space left on device |
29 | Illegal seek |
30 | Read-only file system |
31 | Too many links |
32 | Broken pipe |
33 | Numerical argument out of domain |
34 | Numerical result out of range |
35 | Resource deadlock avoided |
36 | File name too long |
37 | No locks available |
38 | Function not implemented |
39 | Directory not empty |
40 | Too many levels of symbolic links |
42 | No message of desired type |
43 | Identifier removed |
44 | Channel number out of range |
45 | Level 2 not synchronized |
46 | Level 3 halted |
47 | Level 3 reset |
48 | Link number out of range |
49 | Protocol driver not attached |
50 | No CSI structure available |
51 | Level 2 halted |
52 | Invalid exchange |
53 | Invalid request descriptor |
54 | Exchange full |
55 | No anode |
56 | Invalid request code |
57 | Invalid slot |
59 | Bad font file format |
60 | Device not a stream |
61 | No data available |
62 | Timer expired |
63 | Out of streams resources |
64 | Machine is not on the network |
65 | Package not installed |
66 | Object is remote |
67 | Link has been severed |
68 | Advertise error |
69 | Srmount error |
70 | Communication error on send |
71 | Protocol error |
72 | Multihop attempted |
73 | RFS specific error |
74 | Bad message |
75 | Value too large for defined data type |
76 | Name not unique on network |
77 | File descriptor in bad state |
78 | Remote address changed |
79 | Can not access a needed shared library |
80 | Accessing a corrupted shared library |
81 | .lib section in a.out corrupted |
82 | Attempting to link in too many shared libraries |
83 | Cannot exec a shared library directly |
84 | Invalid or incomplete multibyte or wide character |
85 | Interrupted system call should be restarted |
86 | Streams pipe error |
87 | Too many users |
88 | Socket operation on non-socket |
89 | Destination address required |
90 | Message too long |
91 | Protocol wrong type for socket |
92 | Protocol not available |
93 | Protocol not supported |
94 | Socket type not supported |
95 | Operation not supported |
96 | Protocol family not supported |
97 | Address family not supported by protocol |
98 | Address already in use |
99 | Cannot assign requested address |
100 | Network is down |
101 | Network is unreachable |
102 | Network dropped connection on reset |
103 | Software caused connection abort |
104 | Connection reset by peer |
105 | No buffer space available |
106 | Transport endpoint is already connected |
107 | Transport endpoint is not connected |
108 | Cannot send after transport endpoint shutdown |
109 | Too many references |
110 | Connection timed out |
111 | Connection refused |
112 | Host is down |
113 | No route to host |
114 | Operation already in progress |
115 | Operation now in progress |
116 | Stale file handle |
117 | Structure needs cleaning |
118 | Not a XENIX named type file |
119 | No XENIX semaphores available |
120 | Is a named type file |
121 | Remote I/O error |
122 | Disk quota exceeded |
123 | No medium found |
125 | Operation canceled |
126 | Command invoked cannot execute / Required key not available |
127 | Command not found / Key has expired |
128 | Invalid exit argument / Key has been revoked |
129 | Signal 1 return / Key was rejected by service |
130 | Signal 2 return / Owner died |
131 | Signal 3 return / State not recoverable |
132 | Signal 4 return / Operation not possible due to RF-kill |
133 | Signal 5 return / Memory page has hardware error |
134-192 | Signal 6-64 return / Unspecified |
193–254 | Reserved / Unspecified |
255 | Exit status out of range / Critical script or program error |
The author of the software/script may impose their own meaning on specific codes.
The table presents examples for Bash as both an interpreter and a shell.
The most commonly encountered/used return codes include, among others:
- Code 0 – the code returned after a process finishes successfully. It indicates that everything went smoothly.
- Code 1 – a universal "general" code indicating unspecified/other errors. Often used in scripts or programs where it’s hard to assign a specific code to an event.
- Code 126 – the code returned by the shell/interpreter when attempting to execute an invalid/incompatible executable or an executable without proper x permissions.
- Code 127 – returned by the shell when trying to run a non-existent script or program, or a command not found in $PATH.
- Code 130 – returned when a script/program is terminated by a SIGINT signal (CTRL + C). It indicates the process was manually interrupted/canceled.
- Code 255 – similar to code 1, but often used for critical errors. Used in scripts/programs for critical unspecified errors.
`exit` and `return`
Both return and exit are commands used in programming and scripting to provide a return code, signaling the outcome of a process, function, or script. They serve to communicate success, failure, or specific error states to the calling environment or other programs. While they are related in purpose, they are used in different contexts and have distinct behaviors.
Exit: The exit command is used to terminate an entire script or program immediately and return a specific return code to the operating system or calling process. Once executed, no further commands in the script are run (except trap command), and the return code becomes the script’s final status. It is commonly used in shell scripts, batch files, and programs to signal that a process has finished, whether successfully or due to an error.
Return: The return command, on the other hand, is primarily used within functions or subroutines to exit that function and provide a return code to the calling function or script. Unlike exit, it does not terminate the entire script but only the current function, allowing the rest of the script to continue executing. It’s essential for modular programming and for functions to communicate their results back to the main script logic.
It’s important to note that the behavior of exit and return also depends on the context in which the script is running. The exit command terminates scripts executed directly from a shell, ending the script and returning the code to the shell. However, when used in shell initialization or configuration scripts, exit will close the shell itself along with the terminal, which is usually undesirable. In such cases, return is preferred, as it ends the execution of the initialization or configuration script without closing the shell, allowing the terminal session to continue running normally.
Exit: The exit command is used to terminate an entire script or program immediately and return a specific return code to the operating system or calling process. Once executed, no further commands in the script are run (except trap command), and the return code becomes the script’s final status. It is commonly used in shell scripts, batch files, and programs to signal that a process has finished, whether successfully or due to an error.
Return: The return command, on the other hand, is primarily used within functions or subroutines to exit that function and provide a return code to the calling function or script. Unlike exit, it does not terminate the entire script but only the current function, allowing the rest of the script to continue executing. It’s essential for modular programming and for functions to communicate their results back to the main script logic.
It’s important to note that the behavior of exit and return also depends on the context in which the script is running. The exit command terminates scripts executed directly from a shell, ending the script and returning the code to the shell. However, when used in shell initialization or configuration scripts, exit will close the shell itself along with the terminal, which is usually undesirable. In such cases, return is preferred, as it ends the execution of the initialization or configuration script without closing the shell, allowing the terminal session to continue running normally.
You cannot use exit in scripts/functions sourced in shell initialization files (e.g., .bashrc, .zshrc, etc.). Using exit in this context will immediately close the shell along with the terminal.
returns in scripts
Values from return codes can be used, for example, in Bash scripts for communication between functions, for use in loops, and so on. Below are a few examples of using return codes as well as the return command itself.
As the first example, let’s take the until loop (the opposite of a while loop), which runs (in this case) until a non-zero value is returned by return. This loop treats 0 as true and 1..255 as false.
Similarly, the return code status can be used in conditional if statements.
An if condition evaluates true for a returned code of 0 and false for any other value.
In the example, however, it is shown literally that if itself can only distinguish between 0 and non-0.
Here, I will also introduce a new symbol into the article: $?.
The variable $? stores the return code of the previously executed command/process. It behaves just like any other variable - it can be used in code, in conditions, and displayed, for example, with echo.
In the screenshot above, you can see how the return code 5 is set (also indicated by the graphical element of the prompt), which is then displayed using echo $?.
The example above is once again a simple demonstration of obtaining information from the return code in a basic if condition, but this time using the $? variable, which tells us exactly which code was returned.
You can freely use another condition inside the current one to check [ $? -eq X ] or something similar (to prepare different actions depending on the returned code), or…
The next example is a bit more meaningful - after executing a command, we use a case switch to perform specific tasks more precisely depending on the returned return code.
In this particular use case, return codes don’t necessarily have to indicate errors at all, but rather represent general values. Want me to provide an example?
In this slightly abstract example, the return command passes, in a way, the number of lines of some file as the exit status of the function, which can then be read afterward. Perhaps someone might find a concrete use for this approach instead of creating global or local variables - this value is only preserved until the next command is executed.
Another (and the last one for now), somewhat imaginary and rather uncommon example is counting the number of errors from functions executed in bulk, one after another.
until false; do
# do something
if ! something; then
return 1
fi
done
if some-command; then
echo "Returned: success"
else
echo "Returned: error"
fi
In the example, however, it is shown literally that if itself can only distinguish between 0 and non-0.
Here, I will also introduce a new symbol into the article: $?.

In the screenshot above, you can see how the return code 5 is set (also indicated by the graphical element of the prompt), which is then displayed using echo $?.
if some-command; then
echo "Returned: 0"
else
echo "Returned: $?"
fi
You can freely use another condition inside the current one to check [ $? -eq X ] or something similar (to prepare different actions depending on the returned code), or…
some-command
case $? in
0) echo "Success" ;;
1) echo "Some error occured" ;;
126) echo "Command not found" ;;
255) echo "Some error occured" ;;
esac
In this particular use case, return codes don’t necessarily have to indicate errors at all, but rather represent general values. Want me to provide an example?
count_lines() {
return $( wc -l < some_file.txt )
}
count_lines
echo "Lines count: $?"
func1() {
# do something
if ! something; then
return 1
fi
}
func2() {
# do something
if ! something; then
return 1
fi
}
func3() {
# do something
if ! something; then
return 1
fi
}
STATUS=0
for F in {1..3}; do
func${F}
STATUS=$(( STATUS + $? ))
done
echo "$STATUS of 3 functions failed."
outro
Return codes may seem like a small detail, but they play a key role in how Linux and shell environments communicate success, failure, and specific states.
By understanding how exit, return, and the $? variable work, you can write more reliable scripts, handle errors more gracefully, and even design your own logic using exit codes.
In short: mastering return codes means mastering control over your scripts and processes.
By understanding how exit, return, and the $? variable work, you can write more reliable scripts, handle errors more gracefully, and even design your own logic using exit codes.
In short: mastering return codes means mastering control over your scripts and processes.